//
//  API_AsyncSequence_BluetoothVC.swift
//  APSwift
//
//  Created by jianbo.pei on 2024/8/16.
//

import UIKit
import CoreBluetooth

class API_AsyncSequence_BluetoothVC: UIViewController {
    
    // UI 组件
    private lazy var scanButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("开始扫描", for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
        button.backgroundColor = UIColor.systemBlue
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 8
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()
    
    private lazy var stopButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("停止扫描", for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
        button.backgroundColor = UIColor.systemRed
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 8
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()
    
    private lazy var statusLabel: UILabel = {
        let label = UILabel()
        label.text = "蓝牙未初始化"
        label.textAlignment = .center
        label.font = UIFont.systemFont(ofSize: 16)
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    private lazy var logTextView: UITextView = {
        let textView = UITextView()
        textView.isEditable = false
        textView.font = UIFont.monospacedSystemFont(ofSize: 14, weight: .regular)
        textView.backgroundColor = UIColor.systemGray6
        textView.layer.cornerRadius = 8
        textView.translatesAutoresizingMaskIntoConstraints = false
        return textView
    }()
    
    // 蓝牙管理器和任务
    private var bluetoothManager: BluetoothAsyncManager?
    private var scanTask: Task<Void, Never>?
    private var stateTask: Task<Void, Never>?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        setupBluetoothManager()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // 取消所有异步任务
        scanTask?.cancel()
        stateTask?.cancel()
    }
    
    private func setupUI() {
        view.backgroundColor = .white
        title = "蓝牙 AsyncSequence 示例"
        
        view.addSubview(scanButton)
        view.addSubview(stopButton)
        view.addSubview(statusLabel)
        view.addSubview(logTextView)
        
        NSLayoutConstraint.activate([
            scanButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50),
            scanButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 50),
            scanButton.widthAnchor.constraint(equalToConstant: 120),
            scanButton.heightAnchor.constraint(equalToConstant: 50),
            
            stopButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50),
            stopButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 50),
            stopButton.widthAnchor.constraint(equalToConstant: 120),
            stopButton.heightAnchor.constraint(equalToConstant: 50),
            
            statusLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            statusLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            statusLabel.topAnchor.constraint(equalTo: scanButton.bottomAnchor, constant: 30),
            
            logTextView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            logTextView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            logTextView.topAnchor.constraint(equalTo: statusLabel.bottomAnchor, constant: 20),
            logTextView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20)
        ])
        
        // 添加按钮事件
        scanButton.addTarget(self, action: #selector(startScanning), for: .touchUpInside)
        stopButton.addTarget(self, action: #selector(stopScanning), for: .touchUpInside)
        
        // 初始状态
        stopButton.isEnabled = false
    }
    
    private func setupBluetoothManager() {
        bluetoothManager = BluetoothAsyncManager()
        
        // 监听蓝牙状态变化
        stateTask = Task { [weak self] in
            guard let self = self, let manager = self.bluetoothManager else { return }
            
            for await state in manager.stateStream {
                if Task.isCancelled { break }
                
                await MainActor.run {
                    self.handleBluetoothStateChange(state)
                }
            }
        }
    }
    
    private func handleBluetoothStateChange(_ state: CBManagerState) {
        let stateString: String
        let canScan: Bool
        
        switch state {
        case .unknown:
            stateString = "未知状态"
            canScan = false
        case .resetting:
            stateString = "重置中"
            canScan = false
        case .unsupported:
            stateString = "不支持蓝牙"
            canScan = false
        case .unauthorized:
            stateString = "未授权"
            canScan = false
        case .poweredOff:
            stateString = "蓝牙已关闭"
            canScan = false
        case .poweredOn:
            stateString = "蓝牙已开启"
            canScan = true
        @unknown default:
            stateString = "未知状态"
            canScan = false
        }
        
        statusLabel.text = "蓝牙状态: \(stateString)"
        scanButton.isEnabled = canScan && scanTask == nil
        
        appendLog("蓝牙状态变更: \(stateString)")
    }
    
    @objc private func startScanning() {
        guard let manager = bluetoothManager else { return }
        
        scanButton.isEnabled = false
        stopButton.isEnabled = true
        
        appendLog("开始扫描蓝牙设备...")
        
        scanTask = Task { [weak self] in
            guard let self = self else { return }
            
            do {
                for try await device in manager.discoveredDevicesStream {
                    if Task.isCancelled { break }
                    
                    await MainActor.run {
                        self.handleDiscoveredDevice(device)
                    }
                }
            } catch {
                await MainActor.run {
                    self.appendLog("扫描错误: \(error)")
                    self.stopScanning()
                }
            }
        }
        
        manager.startScanning()
    }
    
    @objc private func stopScanning() {
        bluetoothManager?.stopScanning()
        scanTask?.cancel()
        scanTask = nil
        
        scanButton.isEnabled = true
        stopButton.isEnabled = false
        
        appendLog("停止扫描")
    }
    
    private func handleDiscoveredDevice(_ device: BluetoothDevice) {
        let deviceName = device.name ?? "未知设备"
        let rssi = device.rssi
        let timestamp = DateFormatter.localizedString(from: Date(), dateStyle: .none, timeStyle: .medium)
        
        let logMessage = "[\(timestamp)] 发现设备: \(deviceName) (RSSI: \(rssi) dBm)"
        appendLog(logMessage)
    }
    
    private func appendLog(_ message: String) {
        let currentText = logTextView.text ?? ""
        logTextView.text = currentText + message + "\n"
        
        // 滚动到底部
        let bottom = NSMakeRange(logTextView.text.count - 1, 1)
        logTextView.scrollRangeToVisible(bottom)
    }
}

// MARK: - 蓝牙设备数据模型
struct BluetoothDevice {
    let peripheral: CBPeripheral
    let advertisementData: [String: Any]
    let rssi: NSNumber
    
    var name: String? {
        return peripheral.name ?? advertisementData[CBAdvertisementDataLocalNameKey] as? String
    }
}

// MARK: - 蓝牙异步管理器
class BluetoothAsyncManager: NSObject {
    private var centralManager: CBCentralManager!
    private var stateContinuation: AsyncStream<CBManagerState>.Continuation?
    private var deviceContinuation: AsyncStream<BluetoothDevice>.Continuation?
    
    // 状态流
    lazy var stateStream: AsyncStream<CBManagerState> = {
        AsyncStream { continuation in
            self.stateContinuation = continuation
            continuation.onTermination = { _ in
                self.stateContinuation = nil
            }
        }
    }()
    
    // 发现设备流
    lazy var discoveredDevicesStream: AsyncStream<BluetoothDevice> = {
        AsyncStream { continuation in
            self.deviceContinuation = continuation
            continuation.onTermination = { _ in
                self.deviceContinuation = nil
            }
        }
    }()
    
    override init() {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }
    
    func startScanning() {
        guard centralManager.state == .poweredOn else { return }
        centralManager.scanForPeripherals(withServices: nil, options: nil)
    }
    
    func stopScanning() {
        centralManager.stopScan()
    }
}

// MARK: - CBCentralManagerDelegate
extension BluetoothAsyncManager: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        stateContinuation?.yield(central.state)
    }
    
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        let device = BluetoothDevice(
            peripheral: peripheral,
            advertisementData: advertisementData,
            rssi: RSSI
        )
        deviceContinuation?.yield(device)
    }
}